package com.ptswitch.material.services;

import javax.servlet.ServletContext;
import javax.sql.DataSource;

import org.apache.tapestry5.NullFieldStrategy;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.internal.services.IgnoredPathsFilter;
import org.apache.tapestry5.ioc.Configuration;
import org.apache.tapestry5.ioc.MappedConfiguration;
import org.apache.tapestry5.ioc.ObjectLocator;
import org.apache.tapestry5.ioc.ServiceBinder;
import org.apache.tapestry5.ioc.annotations.Contribute;
import org.apache.tapestry5.ioc.annotations.Local;
import org.apache.tapestry5.ioc.annotations.Marker;
import org.apache.tapestry5.ioc.annotations.Startup;
import org.apache.tapestry5.ioc.annotations.SubModule;
import org.apache.tapestry5.ioc.services.ApplicationDefaults;
import org.apache.tapestry5.ioc.services.RegistryShutdownHub;
import org.apache.tapestry5.ioc.services.ServiceOverride;
import org.apache.tapestry5.services.HttpServletRequestFilter;
import org.apache.tapestry5.services.NullFieldStrategySource;
import org.apache.tapestry5.services.RequestExceptionHandler;
import org.apache.tapestry5.services.URLEncoder;
import org.hxzon.tapestry5.services.HxzonTapestryModule;
import org.hxzon.tapestry5.util.Base64UrlEncoderImpl;
import org.hxzon.tapestry5.util.EmptyNullFieldStrategy;
import org.hxzon.tapestry5.util.MyRequestExceptionHandler;
import org.hxzon.util.db.Db;
import org.slf4j.Logger;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.ptswitch.material.service.AdmCmdService;
import com.ptswitch.material.service.HTreeService;
import com.ptswitch.material.service.PermissionService;
import com.ptswitch.material.service.RoleService;
import com.ptswitch.material.service.UserService;
import com.ptswitch.material.util.Gs;
import com.ptswitch.material.util.MaterialUtil;
import com.ptswitch.material.util.WebUtil;

@SubModule({ HxzonTapestryModule.class })
public class AppModule {
    @Startup
    public static void init(ServletContext servletContext, Logger logger) {
        String contextRealPath = servletContext.getRealPath("");
        logger.info("contextPath:" + contextRealPath);
        if (contextRealPath == null) {
            contextRealPath = "";
        }
        WebUtil.init(contextRealPath, contextRealPath + "/WEB-INF/upload/");
        MaterialUtil.init(contextRealPath);
    }

    @Startup
    public static void init(PermissionService permissionSer, RoleService roleSer, UserService userSer) {
        permissionSer.initPermissions();
        roleSer.initRoles();
        userSer.initUsers();
    }

    @Startup
    public static void init(HTreeService htreeSer) {
        htreeSer.init();
    }

    @Startup
    public static void init(final AdmCmdService admCmdSer, ObjectLocator locator, ServletContext servletContext,//
            RegistryShutdownHub shutdownHub) {
        Gs.init(locator, WebApplicationContextUtils.getWebApplicationContext(servletContext));
        Gs.addDb(new Db("main", Gs.getSer(DataSource.class)));
        admCmdSer.start();
        shutdownHub.addRegistryShutdownListener(new Runnable() {
            @Override
            public void run() {
                admCmdSer.stop();
            }
        });
    }

    public static void bind(ServiceBinder binder) {
        binder.bind(RequestExceptionHandler.class, MyRequestExceptionHandler.class).withId("MyRequestExceptionHandler");
        binder.bind(URLEncoder.class, Base64UrlEncoderImpl.class).withId("MyURLEncoder");
    }

    @ApplicationDefaults
    public static void contributeApplicationDefaults(MappedConfiguration<String, String> configuration) {
        configuration.add(SymbolConstants.COOKIE_MAX_AGE, "14 d");
        configuration.add(SymbolConstants.HMAC_PASSPHRASE, "mstar");
    }

    @Contribute(NullFieldStrategySource.class)
    public static void contributeNullFieldStrategySource(MappedConfiguration<String, NullFieldStrategy> configuration) {
        configuration.override("default", new EmptyNullFieldStrategy());
    }

    @Contribute(HttpServletRequestFilter.class)
    @Marker(IgnoredPathsFilter.class)
    public static void contributeIgnoredPathsFilter(Configuration<String> configuration) {
        configuration.add("/zkau/web/.*");
        configuration.add("/zkau/.*");
        configuration.add("/zkau");
//        configuration.add(".*\\.css");
//        configuration.add(".*\\.js");
    }

    @Contribute(ServiceOverride.class)
    public static void contributeServiceOverride(MappedConfiguration<Class<?>, Object> configuration, //
            @Local RequestExceptionHandler overrideRequestExceptionHandler,//
            @Local URLEncoder urlEncoder) {
        configuration.add(RequestExceptionHandler.class, overrideRequestExceptionHandler);
        configuration.add(URLEncoder.class, urlEncoder);
    }

}
